package com.wanwu.channel.facade.impl.template;


import com.wanwu.channel.common.enums.ExceptionEnum;
import com.wanwu.channel.common.exception.SystemException;
import com.wanwu.channel.common.util.LogUtil;
import com.wanwu.channel.facade.dto.req.ChBaseReqDto;
import com.wanwu.channel.facade.dto.resp.ChBaseRespDto;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;

/**
 * @author JiWen
 * @time 2020/1/31 01:28
 */
public abstract class FacadeTemplate<T extends ChBaseReqDto, R extends ChBaseRespDto> {
    protected T req;
    private final String templateName;
    protected Class<R> clazz;


    private static final Logger logger = LoggerFactory.getLogger(FacadeTemplate.class);

    protected FacadeTemplate(String templateName, T req, Class<R> clazz) {
        if (req ==null) {
            throw new SystemException(ExceptionEnum.V10001);
        }
        this.templateName = StringUtils.isEmpty(templateName) ? StringUtils.EMPTY : templateName;
        this.req = req;
        this.clazz = clazz;
    }

    /**
     * 入参非空校验
     * @param req
     */
    protected void checkParams(T req) {
        if (ObjectUtils.isEmpty(req)) {
            throw new SystemException(ExceptionEnum.V10001);
        }
    }

    /**
     * 业务处理
     * @return
     */
    protected abstract R process();

    /**
     * 调用完成后处理
     */
    protected void afterProcess() {
    }

    /**
     * 执行主流程
     * @return
     */
    public final R execute() {
        long timeStart = System.currentTimeMillis();
        R result = null;
        try {
            logger.info(templateName + "接口接收到请求：{}", req);
            checkParams(req);
            result = process();
            if (result == null) {
                result =  clazz.newInstance();
            }
            if (result.getRespCode() == null) {
                result.setRespCode(ExceptionEnum.S00000.name());
                result.setRespMsg(ExceptionEnum.S00000.getMsg());
            }
        } catch (Throwable t) {
            result = handleException(t);
        } finally {
            long elapsedMills = System.currentTimeMillis() - timeStart;
            LogUtil.info(logger, templateName + "接口执行消耗{0}ms，返回结果：{1}， ", elapsedMills, result);
            afterProcess();
        }
        return result;
    }

    private R handleException(Throwable t) {
        logger.error(templateName + "接口发生异常", t);
        R result = null;
        try {
            result =  clazz.newInstance();
            if (t instanceof SystemException) {
                SystemException exception = (SystemException) t;
                result.setRespCode(exception.getCode());
                result.setRespMsg(exception.getMsg());
            } else {
                result.setRespCode(ExceptionEnum.E10000.name());
                result.setRespMsg(ExceptionEnum.E10000.getMsg());
            }
            result.setRespSts(ExceptionEnum.FAIL.name());
        } catch (Exception e) {
            if(null != result){
                LogUtil.error(logger, e, "Unable to create facade response of clazz: " + result.getClass());
            }else {
                LogUtil.error(logger, e, "Unable to create facade response ");
            }

        }
        return result;
    }
}

